/**
 * 错误处理器
 * 统一处理API请求过程中的各种错误
 */

import { message } from 'antd';

/**
 * 错误类型枚举
 */
export enum ErrorType {
  /** 网络错误 */
  NETWORK_ERROR = 'NETWORK_ERROR',
  /** HTTP错误 */
  HTTP_ERROR = 'HTTP_ERROR',
  /** 业务错误 */
  BUSINESS_ERROR = 'BUSINESS_ERROR',
  /** 验证错误 */
  VALIDATION_ERROR = 'VALIDATION_ERROR',
  /** 认证错误 */
  AUTH_ERROR = 'AUTH_ERROR',
  /** 权限错误 */
  PERMISSION_ERROR = 'PERMISSION_ERROR',
  /** 超时错误 */
  TIMEOUT_ERROR = 'TIMEOUT_ERROR',
  /** 未知错误 */
  UNKNOWN_ERROR = 'UNKNOWN_ERROR',
}

/**
 * 错误信息配置
 */
const ERROR_MESSAGES: Record<ErrorType, string> = {
  [ErrorType.NETWORK_ERROR]: '网络连接错误，请检查网络设置',
  [ErrorType.HTTP_ERROR]: '请求失败，请稍后重试',
  [ErrorType.BUSINESS_ERROR]: '操作失败，请检查输入信息',
  [ErrorType.VALIDATION_ERROR]: '输入信息不完整或格式错误',
  [ErrorType.AUTH_ERROR]: '登录已过期，请重新登录',
  [ErrorType.PERMISSION_ERROR]: '权限不足，无法执行此操作',
  [ErrorType.TIMEOUT_ERROR]: '请求超时，请检查网络连接',
  [ErrorType.UNKNOWN_ERROR]: '系统错误，请联系管理员',
};

/**
 * HTTP状态码到错误类型的映射
 */
const HTTP_STATUS_MAP: Record<number, ErrorType> = {
  400: ErrorType.VALIDATION_ERROR,
  401: ErrorType.AUTH_ERROR,
  403: ErrorType.PERMISSION_ERROR,
  404: ErrorType.HTTP_ERROR,
  408: ErrorType.TIMEOUT_ERROR,
  500: ErrorType.HTTP_ERROR,
  502: ErrorType.NETWORK_ERROR,
  503: ErrorType.NETWORK_ERROR,
  504: ErrorType.TIMEOUT_ERROR,
};

/**
 * 自定义错误类
 */
export class AppError extends Error {
  constructor(
    public type: ErrorType,
    message?: string,
    public details?: any,
    public originalError?: Error
  ) {
    super(message || ERROR_MESSAGES[type]);
    this.name = 'AppError';
    
    // 保持错误堆栈
    if (originalError && originalError.stack) {
      this.stack = `${this.stack}\nCaused by: ${originalError.stack}`;
    }
  }
}

/**
 * 错误处理器类
 */
export class ErrorHandler {
  private static instance: ErrorHandler;
  private errorCallbacks: ((error: AppError) => void)[] = [];

  private constructor() {}

  /**
   * 获取单例实例
   */
  public static getInstance(): ErrorHandler {
    if (!ErrorHandler.instance) {
      ErrorHandler.instance = new ErrorHandler();
    }
    return ErrorHandler.instance;
  }

  /**
   * 注册错误回调
   */
  public onError(callback: (error: AppError) => void): void {
    this.errorCallbacks.push(callback);
  }

  /**
   * 移除错误回调
   */
  public offError(callback: (error: AppError) => void): void {
    const index = this.errorCallbacks.indexOf(callback);
    if (index > -1) {
      this.errorCallbacks.splice(index, 1);
    }
  }

  /**
   * 处理错误
   */
  public handleError(error: any, context?: string): void {
    const appError = this.normalizeError(error, context);
    
    // 触发错误回调
    this.errorCallbacks.forEach(callback => {
      try {
        callback(appError);
      } catch (callbackError) {
        console.error('错误回调执行失败:', callbackError);
      }
    });

    // 根据错误类型显示不同的提示
    this.showErrorNotification(appError);

    // 特殊错误处理
    this.handleSpecialErrors(appError);

    // 开发环境记录详细错误信息
    if (process.env.NODE_ENV === 'development') {
      console.error('🚨 [ErrorHandler] 错误详情:', {
        type: appError.type,
        message: appError.message,
        context,
        details: appError.details,
        stack: appError.stack,
      });
    }
  }

  /**
   * 将任意错误转换为 AppError
   */
  private normalizeError(error: any, context?: string): AppError {
    if (error instanceof AppError) {
      return error;
    }

    let errorType = ErrorType.UNKNOWN_ERROR;
    let message = error?.message;
    let details = error?.response?.data || error;

    // 处理 Axios 错误
    if (error?.isAxiosError) {
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {
        errorType = ErrorType.TIMEOUT_ERROR;
      } else if (error.response) {
        // HTTP 错误
        const status = error.response.status;
        errorType = HTTP_STATUS_MAP[status] || ErrorType.HTTP_ERROR;
        
        // 尝试从响应数据中提取错误信息
        if (error.response.data) {
          if (typeof error.response.data === 'string') {
            message = error.response.data;
          } else if (error.response.data.message) {
            message = error.response.data.message;
          } else if (error.response.data.error) {
            message = error.response.data.error;
          }
        }
      } else if (error.request) {
        // 网络错误
        errorType = ErrorType.NETWORK_ERROR;
      }
    }

    // 处理业务错误
    if (error?.code && typeof error.code === 'string') {
      if (error.code.includes('VALIDATION') || error.code.includes('FORMAT')) {
        errorType = ErrorType.VALIDATION_ERROR;
      } else if (error.code.includes('AUTH') || error.code.includes('LOGIN')) {
        errorType = ErrorType.AUTH_ERROR;
      } else if (error.code.includes('PERMISSION') || error.code.includes('ACCESS')) {
        errorType = ErrorType.PERMISSION_ERROR;
      }
    }

    // 添加上下文信息
    if (context) {
      message = `${context}: ${message}`;
    }

    return new AppError(errorType, message, details, error);
  }

  /**
   * 显示错误通知
   */
  private showErrorNotification(error: AppError): void {
    const config = {
      duration: 5, // 5秒后自动关闭
      key: `error_${Date.now()}`,
    };

    switch (error.type) {
      case ErrorType.AUTH_ERROR:
        message.error({
          ...config,
          content: error.message,
          onClose: () => {
            // 跳转到登录页
            localStorage.removeItem('access_token');
            window.location.href = '/login';
          },
        });
        break;

      case ErrorType.PERMISSION_ERROR:
        message.warning({
          ...config,
          content: error.message,
        });
        break;

      case ErrorType.VALIDATION_ERROR:
        message.warning({
          ...config,
          content: error.message,
        });
        break;

      case ErrorType.NETWORK_ERROR:
      case ErrorType.TIMEOUT_ERROR:
        message.error({
          ...config,
          content: error.message,
        });
        break;

      case ErrorType.BUSINESS_ERROR:
        message.error({
          ...config,
          content: error.message,
        });
        break;

      default:
        message.error({
          ...config,
          content: error.message,
        });
        break;
    }
  }

  /**
   * 处理特殊错误
   */
  private handleSpecialErrors(error: AppError): void {
    switch (error.type) {
      case ErrorType.AUTH_ERROR:
        // 认证错误，清除token并跳转到登录页
        setTimeout(() => {
          localStorage.removeItem('access_token');
          window.location.href = '/login';
        }, 2000);
        break;

      case ErrorType.PERMISSION_ERROR:
        // 权限错误，可以记录日志或发送到监控系统
        this.logSecurityEvent(error);
        break;

      case ErrorType.NETWORK_ERROR:
        // 网络错误，可以尝试重连或显示离线模式
        this.handleNetworkError(error);
        break;

      default:
        break;
    }
  }

  /**
   * 记录安全事件
   */
  private logSecurityEvent(error: AppError): void {
    // 在实际项目中，这里可以发送到安全监控系统
    console.warn('🔒 [Security] 权限错误:', {
      type: error.type,
      message: error.message,
      timestamp: new Date().toISOString(),
      userAgent: navigator.userAgent,
      url: window.location.href,
    });
  }

  /**
   * 处理网络错误
   */
  private handleNetworkError(error: AppError): void {
    // 在实际项目中，这里可以实现离线模式或重试逻辑
    console.warn('🌐 [Network] 网络错误:', {
      type: error.type,
      message: error.message,
      timestamp: new Date().toISOString(),
    });
  }

  /**
   * 创建错误边界包装器
   */
  public withErrorBoundary<T>(
    fn: () => Promise<T>,
    fallback?: () => T,
    context?: string
  ): Promise<T> {
    return fn().catch(error => {
      this.handleError(error, context);
      
      if (fallback) {
        return fallback();
      }
      
      throw error;
    });
  }

  /**
   * 创建重试机制
   */
  public async withRetry<T>(
    fn: () => Promise<T>,
    maxRetries: number = 3,
    delay: number = 1000,
    context?: string
  ): Promise<T> {
    let lastError: AppError;
    
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        return await fn();
      } catch (error) {
        lastError = this.normalizeError(error, context);
        
        // 如果是认证错误或权限错误，不重试
        if (
          lastError.type === ErrorType.AUTH_ERROR ||
          lastError.type === ErrorType.PERMISSION_ERROR ||
          lastError.type === ErrorType.VALIDATION_ERROR
        ) {
          break;
        }
        
        if (attempt < maxRetries) {
          console.warn(`🔄 [Retry] 第 ${attempt} 次重试失败，${delay}ms 后重试:`, lastError.message);
          await this.delay(delay * attempt); // 指数退避
        }
      }
    }
    
    throw lastError!;
  }

  /**
   * 延迟函数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 验证错误是否可恢复
   */
  public isRecoverable(error: AppError): boolean {
    const nonRecoverableErrors = [
      ErrorType.AUTH_ERROR,
      ErrorType.PERMISSION_ERROR,
      ErrorType.VALIDATION_ERROR,
    ];
    
    return !nonRecoverableErrors.includes(error.type);
  }

  /**
   * 获取错误统计信息
   */
  public getErrorStats(): {
    totalErrors: number;
    errorCounts: Record<ErrorType, number>;
    lastErrorTime: Date | null;
  } {
    // 在实际项目中，这里可以返回真实的错误统计
    return {
      totalErrors: 0,
      errorCounts: {} as Record<ErrorType, number>,
      lastErrorTime: null,
    };
  }
}

// 导出单例实例
export const errorHandler = ErrorHandler.getInstance();

export default ErrorHandler;